package com.zy.oauth.listener;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Slf4j
@Component
public class SqlExecutionTimeAspect {

    /**
     * 当Sql运行时间超过该值时。则进行log warn级别题型，否则记录INFO日志。
     */
    private long warnWhenOverTime = 2 * 60 * 1000L;

    @Around("execution(* com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl.*(..))")
    public Object logSqlExecutionTime(ProceedingJoinPoint joinPoint)
            throws Throwable {
        long startTime = System.currentTimeMillis();
        Object result = joinPoint.proceed();
        long costTime = System.currentTimeMillis() - startTime;
        if (costTime > warnWhenOverTime) {
            StringBuilder sb = new StringBuilder();
            sb.append("execute method :").append(joinPoint.getSignature());
            sb.append("args: ").append(arrayToString(joinPoint.getArgs()));
            sb.append(" cost time[").append(costTime).append("]ms");
            log.warn(sb.toString());
        } else if (log.isInfoEnabled()) {
            StringBuilder sb = new StringBuilder();
            sb.append("execute method :").append(joinPoint.getSignature());
            sb.append("args: ").append(arrayToString(joinPoint.getArgs()));
            sb.append(" cost time[").append(costTime).append("]ms");
            log.info(sb.toString());
        }
        return result;
    }

    private static String arrayToString(Object[] a) {
        if (a == null) {
            return "null";
        }

        int iMax = a.length - 1;
        if (iMax == -1) {
            return "[]";
        }

        StringBuilder b = new StringBuilder();
        b.append('[');
        for (int i = 0; ; i++) {
            if (a[i] instanceof Object[]) {
                b.append(arrayToString((Object[]) a[i]));
            } else {
                b.append(String.valueOf(a[i]));
            }
            if (i == iMax) {
                return b.append(']').toString();
            }
            b.append(", ");
        }
    }
}
